package qq2564874169.tuaotuao.fx.orm.query;


import qq2564874169.tuaotuao.fx.Func1T;
import qq2564874169.tuaotuao.fx.utils.ClassUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

public class ChooseField<T> {
    private static Map<Class<?>, ClassFields> fieldMap = new HashMap();
    private Class<T> clazz;
    private List<Field> fs;

    public ChooseField(Class<T> clazz) {
        if (fieldMap.containsKey(clazz) == false) {
            fieldMap.put(clazz, parseFields(clazz));
        }
        this.clazz = clazz;
        this.fs = new ArrayList<>();
    }

    public List<Field> getChooses() {
        return fs;
    }

    public ChooseField<T> choose(Func1T<T, Object> func) {
        ClassFields cf = fieldMap.get(clazz);
        T model = ClassUtil.setNew(clazz);
        setValue(cf, model);
        Object v = func.execute(model);
        if (v != null) {
            fs.add(cf.get(v));
        }
        return this;
    }

    public ChooseField<T> chooses(Func1T<T, Object[]> func) {
        ClassFields cf = fieldMap.get(clazz);
        T model = ClassUtil.setNew(clazz);
        setValue(cf, model);
        Object[] vs = func.execute(model);
        if (vs != null) {
            for (Object v : vs) {
                fs.add(cf.get(v));
            }
        }
        return this;
    }

    private void setValue(ClassFields cf, Object model) {
        for (Object value : cf.keySet()) {
            try {
                cf.get(value).set(model, value);
            } catch (IllegalAccessException ignored) {

            }
        }
    }

    private static ClassFields parseFields(Class<?> clazz) {
        ClassFields cf = new ClassFields();
        List<Field> fs = ClassUtil.fields(clazz);
        for (Field f : fs) {
            if (Modifier.isPublic(f.getModifiers()) == false) {
                continue;
            }
            if (Modifier.isFinal(f.getModifiers())) {
                continue;
            }
            if (Modifier.isStatic(f.getModifiers())) {
                continue;
            }
            if (Modifier.isNative(f.getModifiers())) {
                continue;
            }
            Object value = null;
            if (f.getType() == int.class || f.getType() == Integer.class) {
                value = Integer.MIN_VALUE + Math.abs(f.hashCode());
            } else if (f.getType() == long.class || f.getType() == Long.class) {
                value = Long.MIN_VALUE + Math.abs(f.hashCode());
            } else if (f.getType() == float.class || f.getType() == Float.class) {
                value = Float.MIN_VALUE + Math.abs(f.hashCode());
            } else if (f.getType() == double.class || f.getType() == Double.class) {
                value = Double.MIN_VALUE + Math.abs(f.hashCode());
            } else if (f.getType() == boolean.class || f.getType() == Boolean.class) {
                value = true;
            } else {
                try {
                    value = ClassUtil.setNew(f.getType());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (value != null) {
                cf.put(value, f);
            }
        }
        return cf;
    }

    private static class ClassFields extends LinkedHashMap<Object, Field> {

    }
}
